#! /usr/bin/env python
# -*- coding: utf-8 -*-
from datetime import datetime

from flask_login import UserMixin, AnonymousUserMixin
from sqlalchemy import UniqueConstraint
from werkzeug.security import generate_password_hash, check_password_hash

from app import db, login_manager


class Permission:
    """
    1. administrator
    2. viewer
    """

    VIEW = 0x01
    CHANGE = 0x02
    ADMIN = VIEW | CHANGE


class Role(db.Model):
    __tablename__ = 'roles'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    # default_bool = db.Column(db.Boolean, default=False, index=True)
    permissions = db.Column(db.Integer)
    users = db.relationship('User', backref='role', lazy='dynamic')

    def __repr__(self):
        return '<Role %r>' % self.name

    @staticmethod
    def insert_roles():
        roles = {
            'User': (Permission.VIEW, True),
            'Administrator': (Permission.VIEW | Permission.CHANGE, False)
        }

        for r in roles:
            role = Role.query.filter_by(name=r).first()
            if role is None:
                role = Role(name=r)
            role.permissions = roles[r][0]
            # role.default = roles[r][1]
            db.session.add(role)
        db.session.commit()

    @property
    def name_zh(self):
        choices = {
            "User": u"普通用户",
            "Administrator": u"管理员"
        }
        return choices.get(self.name)


class User(db.Model, UserMixin):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(164), unique=True, index=True)
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
    password_hash = db.Column(db.String(164))
    deleted = db.Column(db.Boolean, default=False)  # 0 正常, 1 删除

    # logs = db.relationship('Log', backref='user', lazy='dynamic')

    @property
    def password(self):
        raise AttributeError('password is not readable')

    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)

    @login_manager.user_loader
    def load_user(user_id):
        return User.query.get(int(user_id))

    def is_admin(self):
        return self.can(Permission.ADMIN)

    def is_viewer(self):
        return self.can(Permission.VIEW)

    def can(self, permissions):
        return self.role is not None and \
               (self.role.permissions & permissions) == permissions

    def change(self, item, value):
        setattr(self, item, value)

    def __repr__(self):
        return "<User %r>" % self.username


class AnonymousUser(AnonymousUserMixin):
    """ anonymous user """

    def is_admin(self):
        return False

    def can(self, permissions):
        return False


class Client(db.Model):
    __tablename__ = 'clients'
    __table_args__ = (UniqueConstraint("icloud", "mobile",
                                       name='icoud_mobile'),)

    id = db.Column(db.Integer, primary_key=True)
    icloud = db.Column(db.String(128), unique=True, index=True)
    icloud_pw = db.Column(db.String(128), default="")
    username = db.Column(db.String(128), nullable=False)
    mobile = db.Column(db.String(128), nullable=False)
    comment = db.Column(db.String(255), default="")
    loans = db.relationship('Loan', backref='client', lazy='dynamic')

    def __repr__(self):
        return "<Client %r: %r>" % (self.icloud, self.username)


class Loan(db.Model):
    __tablename__ = 'loans'

    id = db.Column(db.Integer, primary_key=True)
    money = db.Column(db.Float, default=0)
    commission = db.Column(db.Float, default=0)
    entry = db.Column(db.Integer, default=1)  # 入口 1: 线上 2: 线下
    start_time = db.Column(db.DateTime, nullable=False)
    end_time = db.Column(db.DateTime, nullable=False)
    create_time = db.Column(db.DateTime, nullable=False,
                            default=datetime.now())
    update_time = db.Column(db.DateTime, nullable=False,
                            default=datetime.now())
    iphone = db.Column(db.String(128))
    closed_time = db.Column(db.DateTime, nullable=True)
    status = db.Column(db.Integer)  # 贷款状态 1 贷款中，2 续借
    stage1 = db.Column(db.String(128))  # 初审状态 预设
    stage2 = db.Column(db.String(128))  # 终审状态 预设
    reject_comment = db.Column(db.String(256))  # 拒绝理由 预设
    end = db.Column(db.Integer, default=0)  # 是否结束 0 贷款中 1 正常结清 2 逾期未还 3 逾期还清
    channel = db.Column(db.Integer, default=1)  # 1 支付宝 2 微信 3 转账
    repayment = db.Column(db.Float,  nullable=False, default=0)  # 偿还的前
    comment = db.Column(db.String(256), nullable=True)
    client_id = db.Column(db.Integer, db.ForeignKey('clients.id'))

    def update_loan_log(self, admin, item, value):
        pass

    @property
    def status_words(self):
        choices = {1: u"贷款中", 2: u"续借"}
        return choices.get(int(self.status))

    @property
    def channel_words(self):
        choices = {1: u"支付宝", 2: u"微信", 3: u"转账"}
        return choices.get(int(self.channel))

    @property
    def end_words(self):
        choices = {0: u"贷款中", 1: u"正常结清", 2: u"逾期未还", 3: u"逾期还清", 4: u"续借",
                   5: u"逾期续借"}
        return choices.get(int(self.end))

    @property
    def entry_words(self):
        choices = {1: u"线上", 2: u"线下"}
        return choices.get(int(self.entry))

    def change(self, item, value):
        setattr(self, item, value)
        setattr(self, "update_time", datetime.now())

    def end_loan(self):
        setattr(self, "update_time", datetime.now())
        setattr(self, "closed_time", datetime.now())
        self.end = 1

    def pending_loan(self):
        # end_time be added 8days and change status = 2
        setattr(self, "update_time", datetime.now())
        setattr(self, "closed_time", datetime.now())
        # 如果当前结束时间小于结束时间
        if datetime.now().date() <= self.end_time.date():
            self.end = 4
        else:
            self.end = 5

    def delay_loan(self):
        setattr(self, "update_time", datetime.now())
        self.end = 2

    def delay_loan_ok(self):
        setattr(self, "update_time", datetime.now())
        setattr(self, "closed_time", datetime.now())
        self.end = 3

    def __repr__(self):
        return "<Loan %r: %r>" % (self.id, self.client.username)


login_manager.anonymous_user = AnonymousUser
